home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
Inspectors
/
InspectMe
/
InspectorManager.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
12KB
|
400 lines
// InspectorManager.m
// By Kevin Brain (ksbrain@zeus.UWaterloo.ca)
// A class that manages the displaying of elements of a list of view
// objects that are periodically displayed and removed from a window.
// Compositing techniques and functions from the ToolInspector example
// by Sharon Biocca Zakhour, NeXT Developer Support Team
// You may freely copy, distribute and reuse the code in this example.
// *Everybody involved* disclaims any warranty of any kind, expressed
// or implied, as to its fitness for any particular use.
#import <objc/NXStringTable.h>
#import <appkit/Panel.h>
#import <appkit/View.h>
#import <appkit/PopUpList.h>
#import <appkit/Matrix.h>
#import <objc/Storage.h>
#import <objc/List.h>
#import <appkit/Application.h> // for NXApp
#import <dpsclient/wraps.h> // PScomposite
#import <libc.h>
#import "InspectorManager.h"
@implementation InspectorManager
/* Private functions */
static void
compositeToBuffer(InspectorManager *self,Window *bufferWindow, float srcX, float srcY,
float width, float height, float dstX, float dstY)
{
[[bufferWindow contentView] lockFocus];
PScomposite(srcX, srcY, width, height,
[[self->inspectorPanel contentView] gState], dstX, dstY, NX_COPY);
[[bufferWindow contentView] unlockFocus];
}
static void
compositeToScreen(InspectorManager *self, Window *bufferWindow, float srcX, float srcY,
float width, float height, float dstX, float dstY)
{
[[self->inspectorPanel contentView] lockFocus];
PScomposite(srcX, srcY, width, height,
[[bufferWindow contentView] gState], dstX, dstY, NX_COPY);
[self->inspectorPanel flushWindow];
[[self->inspectorPanel contentView] unlockFocus];
}
/* instance methods */
- init
{
[super init];
if ([NXApp loadNibSection:"Inspector.nib" owner:self] == nil)
NXRunAlertPanel(NULL,"Couldn't load Inspector.nib","OK",NULL,NULL);
/* Tell the Inspector & Palette panels not to become the key window */
[inspectorPanel setBecomeKeyOnlyIfNeeded: YES]; /* This will only */
/* work if you don't miniaturize the panel. */
[inspectorPanel setFloatingPanel:(BOOL)YES];
useKeyEquivalents = YES;
inspectorList = [[Storage alloc] initCount:0 elementSize:sizeof(struct inspectorListEntry)
description:@encode(struct inspectorListEntry)];
groupList = [[Storage alloc] initCount:0 elementSize:sizeof(char *) description:"*"];
visibleInspectors = [[Storage alloc] initCount:0 elementSize:sizeof(unsigned int) description:"i"];
[revertOKOut removeFromSuperview];
[popupOut removeFromSuperview];
[inspectorPanel display]; // to actually remove the controls
[[inspectorPanel contentView] allocateGState];
/* 'messagePanel' is created in IB as the window containing the message inspector*/
/* This window is non-deferred and always kept off-screen */
[self addInspector: messageBox
title:[inspectorStrings valueForStringKey: "MessageInspector"]
atLocation:LOWERLEFTX :LOWERLEFTY cached:NO cacheWindow:messagePanel];
/* Initialize the Inspector to display "Unapplicable Inspector" message */
[self showMessage:(const char *)"Not\nApplicable"];
return self;
}
- (unsigned int)addInspector:(id)theView title:(const char *)theTitle
{
return [self addInspector:theView title:theTitle
atLocation:LOWERLEFTX :LOWERLEFTY cached:YES cacheWindow:nil];
}
- (unsigned int)addInspector:(id)theView title:(const char *)theTitle atLocation:(NXCoord)xLoc :(NXCoord)yLoc
cached:(BOOL)isCached cacheWindow:(id)theCacheWindow
{
struct inspectorListEntry tempInspectorEntry;
NXRect theViewRect;
tempInspectorEntry.view = theView;
tempInspectorEntry.showing = NO;
tempInspectorEntry.cached = isCached;
tempInspectorEntry.title = malloc(sizeof(char)*(strlen((char *)theTitle)));
strcpy(tempInspectorEntry.title,theTitle);
if (isCached) {
if (theCacheWindow == nil) {
[theView getFrame:&theViewRect];
theViewRect.origin.x = [inspectorList count];
tempInspectorEntry.cacheWindow = [[Window alloc] initContent:(const NXRect *)&theViewRect
style:(int)NX_PLAINSTYLE
backing:(int)NX_RETAINED
buttonMask:(int)0
defer:(BOOL)NO];
}
else
tempInspectorEntry.cacheWindow = theCacheWindow;
/* The lockFocus forces the gState to become defined */
[[[tempInspectorEntry.cacheWindow contentView] allocateGState] lockFocus];
[[tempInspectorEntry.cacheWindow contentView] addSubview:theView];
if (theCacheWindow == nil) {
[theView moveTo:0 :0]; // move view to origin of offscreen buffer content view
[tempInspectorEntry.cacheWindow display];
}
[theView getFrame:&tempInspectorEntry.offscreenRect];
// [theView display]; // draw in offscreen buffer
[[tempInspectorEntry.cacheWindow contentView] unlockFocus];
}
[inspectorList addElement:&tempInspectorEntry];
[theView moveTo:xLoc :yLoc];
[theView removeFromSuperview];
return [inspectorList count]-1;
}
- (unsigned int)addGroup:(const char *)theTitle
{
char *tempTitle;
unsigned short temp;
id tempView;
// add item to PopUpList
// command-key equivalents for first 9
if (([groupList count] < 9) && (useKeyEquivalents == YES))
temp = (unsigned short)[groupList count]+(unsigned short)'1';
else
temp = 0; // no command-key equivalent for rest
tempView = [[popupOut target] addItem:theTitle
action:@selector(selectGroup:)
keyEquivalent:temp];
[tempView setTarget:self];
if ([groupList count] == 0) {
// remove the default 'None' item in PopUpList
[[popupOut target] removeItemAt:(unsigned int)0];
[popupOut setTitle:theTitle];
}
if ([groupList count] == 1)
[self showGroupPopUp];
tempTitle = NXCopyStringBuffer((const char *)theTitle);
[groupList addElement:&tempTitle];
return [groupList count]-1;
}
- setUseKeyEquivalents:(BOOL)use
{
useKeyEquivalents = use;
return self;
}
- switchToInspector:(unsigned int)newInspectorNum
{
struct inspectorListEntry *new,*tempOld;
View *tempView;
NXRect tempFrame;
int i,*tempShowing;
unsigned cnt = [visibleInspectors count];
new = [inspectorList elementAt:newInspectorNum];
if (!new) return self; // not a valid inspector
if (new->showing == YES) return self; // if already showing
/* remove all other inspectors */
if (cnt)
for (i=(int)cnt; i > 0;i--) {
tempShowing = [visibleInspectors elementAt:i-1];
tempOld = [inspectorList elementAt:(unsigned int)*tempShowing];
tempOld->showing = NO;
tempView = tempOld->view;
if (tempView != NULL) {
[tempView getFrame:&tempFrame];
if (tempOld->cached)
compositeToBuffer(self, tempOld->cacheWindow, tempFrame.origin.x, tempFrame.origin.y,
NX_WIDTH(&tempFrame),NX_HEIGHT(&tempFrame),
tempOld->offscreenRect.origin.x, tempOld->offscreenRect.origin.y);
[tempView removeFromSuperview];
}
}
[visibleInspectors empty];
[[inspectorPanel contentView] addSubview:new->view];
if (new->cached) {
// Now composite the new inspector view from the offscreen window
// into the inspector panel
[new->view getFrame:&tempFrame];
compositeToScreen(self, new->cacheWindow, new->offscreenRect.origin.x, new->offscreenRect.origin.y,
NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y);
}
else
[new->view display];
[inspectorPanel setTitle:new->title];
new->showing = YES;
i=(int)newInspectorNum;
[visibleInspectors addElement:&i];
return self;
}
- showInspector:(unsigned int)inspectorNum
{
struct inspectorListEntry *new;
NXRect tempFrame;
int tempNum;
new = [inspectorList elementAt:inspectorNum];
if (!new) return self; // not a valid inspector
if ([self showing:inspectorNum] == YES) return self; // if already showing
[inspectorPanel disableFlushWindow];
[[inspectorPanel contentView] addSubview:new->view];
if (new->cached) {
// Now composite the new inspector view from the offscreen window
// into the inspector panel
[new->view getFrame:&tempFrame];
compositeToScreen(self, new->cacheWindow, new->offscreenRect.origin.x, new->offscreenRect.origin.y,
NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y);
}
else
[new->view display];
[inspectorPanel setTitle:new->title];
[inspectorPanel reenableFlushWindow];
[inspectorPanel flushWindowIfNeeded];
new->showing = YES;
tempNum = (int)inspectorNum;
[visibleInspectors addElement:&tempNum];
return self;
}
- hideInspector:(unsigned int)inspectorNum
{
struct inspectorListEntry *inspector;
View *tempView;
NXRect tempFrame;
int i,cnt = [visibleInspectors count],*tempNum;
inspector = [inspectorList elementAt:inspectorNum];
if (!inspector) return self; // not a valid inspector
if(cnt) // find inspectorNum is visibleInspectors list
for (i=cnt; i > 0;i--) {
tempNum = [visibleInspectors elementAt:i-1];
if (inspectorNum == (unsigned)*tempNum) {
[visibleInspectors removeAt:(unsigned)i-1];
inspector->showing = NO;
tempView = inspector->view;
if (tempView != NULL) {
[tempView getFrame:&tempFrame];
if (inspector->cached)
compositeToBuffer(self, inspector->cacheWindow,
tempFrame.origin.x, tempFrame.origin.y,
NX_WIDTH(&tempFrame),NX_HEIGHT(&tempFrame),
inspector->offscreenRect.origin.x, inspector->offscreenRect.origin.y);
[tempView removeFromSuperview];
}
}
}
return self;
}
- (BOOL)showing:(unsigned int)inspectorNum
{
struct inspectorListEntry *inspector;
if (inspectorNum >= [inspectorList count]) return NO; // not a valid inspector
else inspector = [inspectorList elementAt:(unsigned)inspectorNum];
if (inspector->showing == YES) return YES;
else return NO;
}
- (int)group
{
// check if a group is selected (none is initially)
if ([[popupOut target] selectedItem] == NULL)
return 0; // if no group selected, return default group (first group added)
else
return [[popupOut target] indexOfItem:[[popupOut target] selectedItem]];
}
- showMessage:(const char *)theMessage
{
[inspectorPanel disableFlushWindow];
[self switchToInspector:MESSAGE];
[messageTextField setStringValue:theMessage];
[messageTextField display];
[[inspectorPanel reenableFlushWindow] flushWindowIfNeeded];
return self;
}
- messageTextField {return messageTextField; }
- panel
{
return inspectorPanel;
}
- popUpListButton
{
return popupOut;
}
- revertOKMatrix
{
return revertOKOut;
}
- setDelegate:(id)anObject
{
delegate = anObject;
return self;
}
- delegate
{
return delegate;
}
- selectGroup:sender
// target of inspector panel group selector PopUpList
{
[popupOut setTitle:[[sender selectedCell] title]];
[inspectorPanel orderFront:self];
if ([delegate respondsTo:@selector(groupChanged:to:)])
{
[delegate groupChanged:self to:[sender selectedRow]];
}
return self;
}
- revertPressed:sender
// target of inspector panel Revert button
{
if ([delegate respondsTo:@selector(inspectRevert)])
{
[delegate inspectRevert:self];
}
return self;
}
- okPressed:sender
// target of inspector panel OK button
{
if ([delegate respondsTo:@selector(inspectOK)])
{
[delegate inspectOK:self];
}
return self;
}
- showRevertOK
{
[[inspectorPanel contentView] addSubview:revertOKOut];
[revertOKOut display];
return self;
}
- hideRevertOK
{
[revertOKOut removeFromSuperview];
// uncomment the following line to have the Revert/OK buttons
// automatically removed by displaying the contentView
// (otherwise the image of the buttons will still be visible)
// [[inspectorPanel contentView] display];
return self;
}
- showGroupPopUp
{
[[inspectorPanel contentView] addSubview:popupOut];
[popupOut display];
return self;
}
- hideGroupPopUp
{
[popupOut removeFromSuperview];
[[inspectorPanel contentView] display];
return self;
}
@end